﻿#nullable disable
using Android.App;
using Android.Content.PM;
using Android.Graphics;
using Android.Hardware.Camera2;
using Android.Hardware.Camera2.Params;
using Android.OS;
using Android.Runtime;
using Android.Support.V7.App;
using Android.Util;
using Android.Views;
using Android.Widget;
using Java.Lang;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;
using Xamarin.Essentials;
using AlertDialog = Android.App.AlertDialog;
using Environment = System.Environment;
using Exception = System.Exception;

namespace Camera2Demo
{
    [Activity(Label = "@string/app_name", Theme = "@style/AppTheme",
        MainLauncher = true, ScreenOrientation = ScreenOrientation.Portrait)]
    [SuppressMessage("ReSharper", "InconsistentNaming")]
    [SuppressMessage("ReSharper", "PossibleNullReferenceException")]
    public class MainActivity : AppCompatActivity
    {
        private const int LENS_FACING_BACK = 0x_0000_0001;
        private Button _button1;
        private CameraDevice _cameraDevice;
        private CameraManager _cameraManager;
        private bool _isTextureViewOk;
        private TextureView _textureView1;

        public override void OnRequestPermissionsResult(int requestCode,
            string[] permissions,
            [GeneratedEnum] Permission[] grantResults)
        {
            Platform.OnRequestPermissionsResult(requestCode,
                permissions, grantResults);
            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            Platform.Init(this, savedInstanceState);
            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.activity_main);
            // 初始化控件
            _button1 = FindViewById<Button>(Resource.Id.button1);
            _textureView1 = FindViewById<TextureView>(Resource.Id.textureView1);
            // 初始化_cameraManager
            _cameraManager = GetSystemService(CameraService) as CameraManager;
            // 处理控件事件
            _textureView1.SurfaceTextureAvailable +=
                OnTextureView1OnSurfaceTextureAvailable;
            _textureView1.SurfaceTextureUpdated += (sender, args) =>
            {
                using Bitmap bitmap = _textureView1.GetBitmap(10, 10);
                var foo = new
                { bitmap.Width, bitmap.Height, HashCode = bitmap.GetHashCode() };
                Toast.MakeText(this, foo.ToString(), ToastLength.Short).Show();
            };
            _button1.Click += OnButton1OnClick;
        }

        private async Task CheckPermission<T>(string message)
            where T : Permissions.BasePermission, new()
        {
            PermissionStatus status =
                await Permissions.CheckStatusAsync<T>();
            if (status == PermissionStatus.Denied)
            {
                PermissionStatus permissionStatus =
                    await Permissions.RequestAsync<T>();
                if (permissionStatus != PermissionStatus.Granted)
                {
                    var builder = new AlertDialog.Builder(this);
                    builder.SetTitle("提示")
                        .SetMessage(message)
                        .SetPositiveButton("确认", async (o, eventArgs) =>
                        {
                            await CheckPermission<T>(message);
                        })
                        .SetNegativeButton("取消", (o, eventArgs) =>
                        {
                            Finish();
                        })
                        .Show();
                }
            }
        }

        private async void OnButton1OnClick(object sender, EventArgs args)
        {
            _button1.Enabled = false;

            //动态权限申请
            await CheckPermission<Permissions.Camera>("需要相机权限");
            await CheckPermission<Permissions.StorageRead>("需要读存储卡的权限");
            await CheckPermission<Permissions.StorageWrite>("需要写存储卡的权限");

            //判断 _textureView1.SurfaceTextureListener是否初始化完毕
            if (_isTextureViewOk == false)
            {
                var builder = new AlertDialog.Builder(this);
                builder.SetTitle("提示")
                    .SetMessage("相机预览器未准备就绪")
                    .SetPositiveButton("退出", (o, eventArgs) =>
                    {
                    })
                    .Show();
            }

            //获取设备的相机Id
            try
            {
                foreach (string s in _cameraManager.GetCameraIdList())
                {
                    CameraCharacteristics cameraCharacteristics =
                        _cameraManager.GetCameraCharacteristics(s);
                    var i = (int)cameraCharacteristics.Get(CameraCharacteristics
                        .LensFacing);
                    //筛选后置摄像头
                    if (i == LENS_FACING_BACK)
                    {
                        var streamConfigurationMap =
                            cameraCharacteristics.Get(CameraCharacteristics
                                .ScalerStreamConfigurationMap) as
                                StreamConfigurationMap;
                        Size[] sizes =
                            streamConfigurationMap.GetOutputSizes(
                                Class.FromType(typeof(SurfaceTexture)));
                        Size maxSize = SelectMaxSize(sizes);
                        //设置TextureView呈现图片的大小
                        _textureView1.SurfaceTexture.SetDefaultBufferSize(
                            maxSize.Width,
                            maxSize.Height);
                        var cameraStateCallback = new CameraDeviceStateCallback();
                        _cameraManager.OpenCamera(s, cameraStateCallback,
                            default);
                        await cameraStateCallback;
                        _cameraDevice = cameraStateCallback.CameraDevice;
                    }
                }
            }
            catch (Exception e)
            {
                ShowMessage($@"相机初始化失败:{Environment.NewLine}{e}");
                return;
            }

            //从TextureView1创建Surface,用于显示相机的预览流
            var surface = new Surface(_textureView1.SurfaceTexture);
            //CreateCaptureSession
            var sessionStateCallback = new CameraCaptureSessionStateCallback();
            _cameraDevice.CreateCaptureSession(new List<Surface> { surface },
                sessionStateCallback, default);
            await sessionStateCallback;
            //CreateCaptureRequest
            CaptureRequest.Builder requestBuilder =
                _cameraDevice.CreateCaptureRequest(CameraTemplate.Preview);
            requestBuilder.AddTarget(surface);
            //CaptureRequest
            CaptureRequest captureRequest = requestBuilder.Build();
            CameraCaptureSession session = sessionStateCallback.Session;
            var captureCallback = new CameraCaptureSessionCaptureCallback();
            //执行重复请求
            session.SetRepeatingRequest(captureRequest, captureCallback, default);
        }

        private void OnTextureView1OnSurfaceTextureAvailable(object sender,
            TextureView.SurfaceTextureAvailableEventArgs args)
        {
            _isTextureViewOk = true;
        }

        private Size SelectMaxSize(Size[] sizes)
        {
            if (sizes == null) return null;
            Dictionary<int, Size> dictionary =
                (from size in sizes
                 let area = size.Height * size.Width
                 select (size, area)).ToDictionary(tuple => tuple.area,
                     tuple => tuple.size);
            return dictionary[dictionary.Keys.Max()];
        }

        private void ShowMessage(string message)
        {
            var builder = new AlertDialog.Builder(this);
            builder.SetTitle("提示")
                .SetMessage(message)
                .SetPositiveButton("退出", (o, eventArgs) =>
                {
                })
                .Show();
        }
    }
}